/*
 * $Id: Path.cc,v 1.4 2005-06-28 10:53:20 bacon Exp $
 */

#include <xpp/sys/Path.h>
#include <xp/bas/sysapi.h>
#include <xp/bas/assert.h>

namespace xpp
{
	namespace sys
	{

		Path::Path ()
		{
			set_to_root ();
		}
		
		Path::Path (const xp_char_t* n) 
		{
			setName (n);
		}
		
		Path::Path (const Path& fn)
		{
			xp_strxcpy (full_path, xp_countof(full_path), fn.full_path);	
			set_base_name ();
		}
		
		Path& Path::operator= (const Path& fn) 
		{
			xp_strxcpy (full_path, xp_countof(full_path), fn.full_path);	
			set_base_name ();
			return *this;
		}
		
		bool Path::exists (const xp_char_t* path)
		{
			return ::xp_access (path, XP_ACCESS_EXIST) == 0;
		}
		int Path::getSize (xp_off_t* sz)
		{
			xp_stat_t buf;
			if (::xp_stat (full_path, &buf) == -1) return -1;
			*sz = buf.st_size;
			return 0;
		}
		bool Path::isWritable ()
		{
			return ::xp_access (full_path, XP_ACCESS_WRITE) == 0;
		}
		bool Path::isReadable ()
		{
			return ::xp_access (full_path, XP_ACCESS_READ) == 0;
		}

		bool Path::isReadWritable ()
		{
			return ::xp_access (full_path, 
				XP_ACCESS_READ | XP_ACCESS_WRITE) == 0;
		}

#ifndef _WIN32
		bool Path::isExecutable ()
		{
			return ::xp_access (full_path, XP_ACCESS_EXECUTE) == 0;
		}
#endif
		
		bool Path::isDirectory (const xp_char_t* path)
		{
			int n;
			xp_stat_t st;
		
			n = ::xp_stat (path, &st);
			if (n == -1) return 0;
		#ifdef _WIN32
			return (st.st_mode & _S_IFDIR) != 0;
		#else
			return S_ISDIR(st.st_mode);
		#endif
		}
		
		bool Path::isRegular (const xp_char_t* path)
		{
			int n;
			xp_stat_t st;
		
			n = ::xp_stat (path, &st);
			if (n == -1) return 0;
		#ifdef _WIN32
			return (st.st_mode & _S_IFREG) != 0;
		#else
			return S_ISREG(st.st_mode);
		#endif
		}
		
		int Path::chmod (xp_mode_t mode)
		{
			return xp_chmod (full_path, mode);
		}
		
		int Path::chmod (const xp_char_t* path, xp_mode_t mode)
		{
			return xp_chmod (path, mode);
		}

		int Path::unlink ()
		{
			return ::xp_unlink (full_path);
		}

		int Path::mkdir (xp_mode_t mode)
		{
			return ::xp_mkdir (full_path, mode);
		}

		int Path::mkdir (const xp_char_t* path, xp_mode_t mode)
		{
			return ::xp_mkdir (path, mode);
		}
		
		void Path::set_base_name ()
		{
			xp_size_t len = xp_strlen(full_path);
			xp_assert (len > 0);
		
			for (xp_size_t i = len; i > 0; i--) {
		#ifdef _WIN32
				if ((full_path[i - 1] == XP_CHAR('/') ||
				     full_path[i - 1] == XP_CHAR('\\')) && i != len) {
		#else
				
				if (full_path[i - 1] == XP_CHAR('/') && i != len) {
		#endif
					const xp_char_t* p = full_path;
		#ifdef _WIN32
					if (full_path[len-1] == XP_CHAR('/') || 
					    full_path[len-1] == XP_CHAR('\\')) 
		#else
					if (full_path[len - 1] == XP_CHAR('/')) 
		#endif
						xp_strxncpy (
							base_name, xp_countof(base_name), &p[i], len - i - 1);
					else 
						xp_strxncpy (
							base_name, xp_countof(base_name), &p[i], len - i);
		
		#ifdef _WIN32
					if (i == 1 && (full_path[i-1] == XP_CHAR('/') || 
					               full_path[i-1] == XP_CHAR('\\'))) 
		#else
					if (i == 1 && full_path[i-1] == XP_CHAR('/')) 
		#endif
						xp_strxncpy (
							base_dir, xp_countof(base_dir), p, i);
					else 
						xp_strxncpy (
							base_dir, xp_countof(base_dir), p, i - 1);
		
					return;
				}
			}
		
		#ifdef _WIN32
			if (full_path[len-1] == XP_CHAR('/') ||
			    full_path[len-1] == XP_CHAR('\\')) 
		#else
			if (full_path[len-1] == XP_CHAR('/')) 
		#endif
				xp_strxncpy (
					base_name, xp_countof(base_name), full_path, len - 1);
			else 
				xp_strxcpy (
					base_name, xp_countof(base_name), full_path);
		
		#ifdef _WIN32
			if (full_path[(xp_size_t)0] == XP_CHAR('/') || 
			    full_path[(xp_size_t)0] == XP_CHAR('\\'))
		#else
			if (full_path[(xp_size_t)0] == XP_CHAR('/')) 
		#endif
				xp_strcpy (base_dir, XP_TEXT("/"));
			else 
				xp_strcpy (base_dir, XP_TEXT(""));
		}

		void Path::set_to_root ()
		{
			xp_strcpy (full_path, XP_TEXT("/"));
			//set_base_name ();
			xp_strcpy (base_name, XP_TEXT(""));
			xp_strcpy (base_dir,  XP_TEXT("/"));
		}
		
		int Path::setToSelf (const xp_char_t* argv0)
		{
			xp_char_t p[MAX_LEN + 1];
			if (xp_getpnm (argv0, p, xp_countof(p)) == -1) return -1;
			setName (p);
			return 0;
		}

	}		
}
